﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Notoric.Model.Validation
{
    /// <summary>
    /// Abstract base class for a validation rule.
    /// </summary>
    /// <remarks>
    /// A validation rule can be used to check the validity of a new value for some property
    /// before setting it causing potentialy an exception to be thrown.
    /// </remarks>
    /// <seealso cref="IValidator"/>
    public abstract class Rule
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="Rule"/> instance.
        /// </summary>
        /// <param name="propertyName">
        /// <para>
        /// Type: <see cref="System.String"/>
        /// </para>
        /// <para>
        /// Name of the property controlled by this rule (see <see cref="PropertyName"/>)
        /// </para>
        /// </param>
        /// <param name="description">
        /// <para>
        /// Type: <see cref="System.String"/>
        /// </para>
        /// <para>
        /// Description of this rule (see <see cref="Description"/>)
        /// </para>
        /// </param>
        /// <param name="descriptionKey">
        /// <para>
        /// Type: <see cref="System.String"/>
        /// </para>
        /// <para>
        /// Dictionary key of the rule description (see <see cref="DescriptionKey"/>)
        /// </para>
        /// </param>
        public Rule(string propertyName, string description, string descriptionKey)
        {
            PropertyName = propertyName;
            Description = description;
            DescriptionKey = descriptionKey;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets a description of this rule (in english).
        /// </summary>
        public string Description
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the dictionary key for the description of this rule.
        /// </summary>
        /// <remarks>
        /// The dictionary itself needs to be implemented by the user
        /// of this library. This property is just for convenience.
        /// </remarks>
        public string DescriptionKey
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the name of the property that is controlled by this validation rule.
        /// </summary>
        public string PropertyName
        {
            get;
            private set;
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Validates the given value against this rule and returns the result.
        /// </summary>
        /// <param name="value">
        /// <para>
        /// Type: <see cref="System.Object"/>
        /// </para>
        /// <para>
        /// Validated value
        /// </para>
        /// </param>
        /// <returns>
        /// <para>
        /// Type: <see cref="System.Boolean"/>
        /// </para>
        /// <para>
        /// Validation Result:
        /// <see langword="true"/> if the validation was successful, <see langword="false"/> otherwise.
        /// </para>
        /// </returns>
        public abstract bool ValidateValue(object value);

        #endregion
    }
}
